package souralven.jcomicreader.util;

import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
import java.util.logging.Logger;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

public final class ImageUtil {

	private static final Logger LOGGER = Logger.getLogger(ImageUtil.class.getName());
	private static final String BASE_DIR = System.getProperty("user.dir") + "/src/main/resources/images/";
    public static final String JPEG_EXTENSION = "jpeg";
    public static final String JPG_EXTENSION = "jpg";
    public static final String GIF_EXTENSION = "gif";
	public static final String PNG_EXTENSION = "png";

	private ImageUtil() {
	}

	public static final boolean hasImageFormat(final String path) {
	    if (path == null || !path.contains(".")) {
	        return false;
	    }
	    String ext = path.substring(path.lastIndexOf(".") + 1);
        return (JPEG_EXTENSION.equalsIgnoreCase(ext)
            || JPG_EXTENSION.equalsIgnoreCase(ext)
            || GIF_EXTENSION.equalsIgnoreCase(ext)
            || PNG_EXTENSION.equalsIgnoreCase(ext));
	}

	public static final ImageIcon getFavicon() {
		return getImage("icon", PNG_EXTENSION);
	}

	public static final ImageIcon getImage(final String key, final String extension) {
		final String imageName = BASE_DIR + key + "." + extension;
		LOGGER.finest("Loading image " + imageName);
		final ImageIcon icon = new ImageIcon(imageName);
		return icon;
	}

	/**
	 * Devuelve una imagen (buffer) en funcion de la ruta de un archivo
	 * 
	 * @param fileName la ruta del archivo con su nombre
	 * @return BufferedImage la imagen en el buffer
	 */
	public static BufferedImage loadBufferedImage(final String fileName) {
		BufferedImage image = null;
		try {
			image = ImageIO.read(new File(fileName));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return image;
	}

	/**
	 * Devuelve una imagen (buffer) en funcion de un input stream
	 * 
	 * @param stream el stream de la imagen
	 * @return BufferedImage la imagen en el buffer
	 */
	public static BufferedImage loadBufferedImage(final InputStream stream) {
		BufferedImage image = null;
		try {
			image = ImageIO.read(stream);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return image;
	}

	/**
	 * Calcula el factor de escala minimo y en base a eso escala la imagen segun
	 * el dicho factor.
	 * 
	 * @param nMaxWidth minimo tamanio para el ancho
	 * @param nMaxHeight minimo tamanio para el alto
	 * @param imgSrc la imagen
	 * @return un BufferedImage escalado
	 */
	public static BufferedImage scaleToSize(final int nMaxWidth, final int nMaxHeight,
			final BufferedImage imgSrc) {
		final double fScale = getScaleFactor(nMaxWidth, nMaxHeight, imgSrc);
		return scale(fScale, imgSrc);
	}

	/**
	 * Calcula el factor de escala minimo.
	 * 
	 * @param nMaxWidth minimo tamanio para el ancho
	 * @param nMaxHeight minimo tamanio para el alto
	 * @param imgSrc la imagen
	 * @return el factor de escala
	 */
	public static double getScaleFactor(final int nMaxWidth, final int nMaxHeight,
			final BufferedImage imgSrc) {
		final int nHeight = imgSrc.getHeight();
		final int nWidth = imgSrc.getWidth();
		final double scaleX = (double) nMaxWidth / (double) nWidth;
		final double scaleY = (double) nMaxHeight / (double) nHeight;
		return Math.min(scaleX, scaleY);
	}

	/**
	 * Escala una imagen en porcentaje.
	 * 
	 * @param scale ejemplo: scale=0.6 (escala la imagen al 60%)
	 * @param srcImg una imagen BufferedImage
	 * @return un BufferedImage escalado
	 */
	public static BufferedImage scale(final double scale, final BufferedImage srcImg) {
		if (scale == 1) {
			return srcImg;
		}
		final AffineTransformOp op = new AffineTransformOp(AffineTransform
				.getScaleInstance(scale, scale), null);

		return op.filter(srcImg, null);
	}
}
